package com.example.demokotlin

import org.junit.Test


/**
 * 序列测试
 * Sequence 对每个元素逐个执行所有处理步骤。
 * 集合：当 Iterable 的处理包含多个步骤时，它们会优先执行：
 * 每个处理步骤完成并返回其结果——中间集合。
 * 集合全部元素执行一个步骤，生成中间集合，然后中间集合再执行下一个步骤
 * 官网：
 * https://www.kotlincn.net/docs/reference/
 *
 * @author zhouronghua
 * @time 2021/9/22 1:50 下午
 */
class SequenceTest {

    /**
     * 测试产生序列
     *
     * @author zhouronghua
     * @time 2021/9/22 3:53 下午
     */
    @Test
    fun testGenSequence() {
        println("=== 产生序列 ===")
        // 方式一：通过sequenceOf生成序列
        val numbersSequence = sequenceOf("four", "three", "two", "one")
        // Sequence不能显式格式化输出，可以通过toList转换为列表格式化输出
        println(numbersSequence.toList())
        // 方式二：通过generateSequence生成有规律的序列
        // 产生一个序列，初始元素(第一个元素)为1，下一个元素是前一个元素+2
        val oddNumbers = generateSequence(1) { it + 2 } // `it` 是上一个元素
        println(oddNumbers.take(5).toList())
        // 小于10的元素的序列
        val oddNumbersLessThan10 = generateSequence(1) { if (it + 2 < 10) it + 2 else null }
        println(oddNumbersLessThan10.toList())
        // 方式三：通过asSequence将列表转换为序列
        println("序列元素")
        val numbers = listOf(1, 20, 24, 35)
        val numberSeq = numbers.asSequence();
        numberSeq.forEach {
            println(it)
        }
        /**
         * 方式四：通过sequence生成序列
         * 有一个函数可以逐个或按任意大小的组块生成序列元素——sequence() 函数。 此函数采用一个 lambda 表达式，
         * 其中包含 yield() 与 yieldAll() 函数的调用。 它们将一个元素返回给序列使用者，
         * 并暂停 sequence() 的执行，直到使用者请求下一个元素。
         * yield() 使用单个元素作为参数；
         * yieldAll() 中可以采用 Iterable 对象、Iterable 或其他 Sequence。yieldAll() 的 Sequence 参数可以是无限的。
         */
        val muSeq = sequence {
            yield(1)
            yieldAll(listOf(3, 6, 9))
            yieldAll(generateSequence(15) { it + 3 })
        }
        // 需要指定获取的个数，否则会产生堆溢出
        println(muSeq.take(20).toList())
    }

    /**
     * 测试序列操作
     *
     * @author zhouronghua
     * @time 2021/9/22 4:42 下午
     */
    @Test
    fun testSequenceOperation() {
        val words = "The quick brown fox jumps over the lazy dog".split(" ")
        println("=== 序列操作 ===")
        // 将列表转换为序列
        val wordsSequence = words.asSequence()
        // 过滤得到其中长度大于3的单词，长度按照降序获取最前面的四个
        val lenSeq = wordsSequence.filter { it.length > 3 }
            // 计算字符串的长度
            .map { it.length }
            // 字符串长度按照降序排列
            .sortedByDescending { it }
        println(lenSeq.toList())
    }
}